package org.fing.edu.uy.esbadp.motor.strategies;

import java.util.List;
import java.util.Random;
import java.util.logging.Level;

import org.fing.edu.uy.esbadp.core.AdpFlowInterface;
import org.fing.edu.uy.esbadp.core.AdpFlowTRN;
import org.fing.edu.uy.esbadp.core.entity.DMRegisteredService;
import org.fing.edu.uy.esbadp.core.entity.GenericTreeNode;
import org.fing.edu.uy.esbadp.core.entity.PropertiesMonitoring;
import org.fing.edu.uy.esbadp.core.interfaces.IAdpStrategy;
import org.fing.edu.uy.esbadp.logger.LoggerADP;
import org.fing.edu.uy.esbadp.motor.comunication.AdmAdaptationComunication;
import org.fing.edu.uy.esbadp.motor.comunication.AdmServiceComunication;

public class AdpStrategyEquivalentService implements IAdpStrategy{

	private static final java.util.logging.Logger logger = LoggerADP.getLogger(AdpStrategyEquivalentService.class.getSimpleName());

	/*
	 * S1_ToCanonical-> S2_FromCanonical -> EquivalentVirtualService -> S2_ToCanonical -> S1_FromCanonical
	 */
	@Override
	public GenericTreeNode<AdpFlowInterface> getAdpTree(DMRegisteredService service,List<DMRegisteredService> equivServices,PropertiesMonitoring properties) {
		try{	
			if (equivServices.size() > 0){		

				Random generator = new Random();
				int indexRand = generator.nextInt(equivServices.size());
				String equivalentName = equivServices.get(indexRand).getVirtualServiceName();
				String serviceName = service.getVirtualServiceName();
				if (service.isCanonicalXSL() && equivServices.get(indexRand).isCanonicalXSL() ){
					//originalToCanonicalPath
					String originalToCanonical = AdmServiceComunication.getToCanonicalXSL(service.getServiceID());
					GenericTreeNode<AdpFlowInterface> treeNode = new GenericTreeNode<AdpFlowInterface>();	
					AdpFlowInterface actionTRN_S1_ToCanonical = new AdpFlowTRN(originalToCanonical,"TO_CANONICAL_" + serviceName);
					treeNode.setData(actionTRN_S1_ToCanonical);
					
					//equivalentFromCanonicalPath
					String equivalentFromCanonical = AdmServiceComunication.getFromCanonicalXSL(equivServices.get(indexRand).getServiceID());
					GenericTreeNode<AdpFlowInterface> S2_FromCanonical = new GenericTreeNode<AdpFlowInterface>();	
					AdpFlowInterface actionTRN_S2_FromCanonical = new AdpFlowTRN(equivalentFromCanonical,"FROM_CANONICAL_" + equivalentName);
					S2_FromCanonical.setData(actionTRN_S2_FromCanonical);
					
					//Equivalent Service
					GenericTreeNode<AdpFlowInterface> virtualService = getAdpNodeVirtualService(equivServices.get(indexRand));
					
					//equivalentToCanonicalPath
					String equivalentToCanonical = AdmServiceComunication.getToCanonicalXSL(equivServices.get(indexRand).getServiceID());
					GenericTreeNode<AdpFlowInterface> S2_ToCanonical = new GenericTreeNode<AdpFlowInterface>();	
					AdpFlowInterface actionTRN_S2_ToCanonical = new AdpFlowTRN(equivalentToCanonical,"TO_CANONICAL_" + equivalentName);
					S2_ToCanonical.setData(actionTRN_S2_ToCanonical);
					
					//originalFromCanonicalPath
					String originalFromCanonical = AdmServiceComunication.getFromCanonicalXSL(service.getServiceID());
					GenericTreeNode<AdpFlowInterface> S1_FromCanonical = new GenericTreeNode<AdpFlowInterface>();	
					AdpFlowInterface actionTRN_S1_FromCanonical = new AdpFlowTRN(originalFromCanonical,"FROM_CANONICAL_"+serviceName);
					S1_FromCanonical.setData(actionTRN_S1_FromCanonical);
					
					// S2_ToCanonical -> S1_FromCanonical
					S2_ToCanonical.addChild(S1_FromCanonical);	
					
					// virtualService -> S2_ToCanonical -> S1_FromCanonical
					virtualService.addChild(S2_ToCanonical);
					
					// S2_FromCanonical -> virtualService -> S2_ToCanonical -> S1_FromCanonical
					S2_FromCanonical.addChild(virtualService);
					
					// S1_ToCanonical-> S2_FromCanonical -> virtualService -> S2_ToCanonical -> S1_FromCanonical
					treeNode.addChild(S2_FromCanonical);
					
					return treeNode;
				}else{
					logger.log(Level.SEVERE,"Not all canonical transformations are defined");
					return null;
				}
				
			}else{
				return null;
			}

		}catch(Exception ex){
			logger.log(Level.SEVERE, "Exception in AdpStrategyEquivalentService...\n See Tarce => [ {0} ]", ex);	
			return null;
		}
	}
	
	/*** equivalent virtual service ***/
	private GenericTreeNode<AdpFlowInterface> getAdpNodeVirtualService(DMRegisteredService equivalent) throws Exception{
		return AdmAdaptationComunication.getAdpNodeForInvokeVirtualService(equivalent); // SNY
	}
	
}
